Skip to content

Fix unhandled JSON.parse in upload metadata parameters#149

Merged
G4brym merged 1 commit intomainfrom
fix/handle-malformed-metadata-json
Mar 9, 2026
Merged

Fix unhandled JSON.parse in upload metadata parameters#149
G4brym merged 1 commit intomainfrom
fix/handle-malformed-metadata-json

Conversation

@G4brym
Copy link
Copy Markdown
Owner

@G4brym G4brym commented Mar 8, 2026

Summary

  • Wraps JSON.parse() calls for customMetadata and httpMetadata query parameters in try-catch blocks in PutObject and CreateUpload endpoints
  • Returns a descriptive 400 Bad Request error instead of crashing with an unhandled 500 Internal Server Error when clients send malformed base64-encoded JSON
  • Adds 4 integration tests covering malformed metadata for both endpoints

What changed

packages/worker/src/modules/buckets/putObject.ts — Added try-catch around JSON.parse(decodeURIComponent(escape(atob(...)))) for both customMetadata and httpMetadata query parameters. On failure, throws HTTPException(400) with a descriptive message.

packages/worker/src/modules/buckets/multipart/createUpload.ts — Same fix applied. Also added the missing HTTPException import from hono/http-exception.

Tests — Added tests in buckets.test.ts and multipart.test.ts that send invalid base64-encoded JSON and verify a 400 response is returned.

Why

Both upload endpoints accept optional customMetadata and httpMetadata as base64-encoded JSON strings in query parameters. If a client sends a valid base64 string that decodes to invalid JSON (or an invalid base64 string), the JSON.parse() call throws an unhandled exception, resulting in a generic 500 error. This makes debugging difficult for API consumers. The fix returns a clear 400 error message indicating which parameter is invalid.

Test plan

  • All 82 worker tests pass (7 skipped — same as baseline)
  • All 110 dashboard tests pass
  • Linter passes with no issues
  • Includes changeset

🤖 Generated with Claude Code

Wrap base64 + JSON decoding of customMetadata and httpMetadata query
parameters in try-catch blocks for PutObject and CreateUpload endpoints.
Previously, malformed input would crash with an unhandled exception
returning a 500 error. Now returns a descriptive 400 error instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
r2-explorer-docs 8581550 Commit Preview URL

Branch Preview URL
Mar 08 2026, 02:08 AM

Copy link
Copy Markdown
Owner Author

@G4brym G4brym left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review — APPROVED ✅

Review Scores: 5/5 reviewers approved

Summary

Reviewed the addition of try-catch guards around JSON.parse(decodeURIComponent(escape(atob(...)))) for customMetadata and httpMetadata in both PutObject and CreateUpload endpoints. The change correctly converts unhandled 500 crashes into descriptive 400 responses. Four new integration tests cover the malformed metadata paths.

Review Perspectives

  1. Correctness: ✅ Try-catch covers the full decode chain (atob → escape → decodeURIComponent → JSON.parse), all failure modes caught
  2. Security: ✅ Improves error handling — static error messages, no user input reflection, uses established HTTPException pattern
  3. Performance: ✅ Negligible overhead from try-catch on a request-handling path
  4. Code Quality: ✅ Consistent pattern across both endpoints, proper import added to createUpload.ts, clear error messages
  5. Testing: ✅ 4 new integration tests verify 400 status and error messages for both parameters on both endpoints

Minor notes (non-blocking)

  • Pre-existing: createUpload.ts uses Response.json() for bucket-not-found but HTTPException for metadata errors — minor inconsistency not introduced by this PR
  • Tests cover invalid JSON in valid base64; could additionally test invalid base64 strings to exercise the atob failure path (both are caught by the same catch block)

🤖 Automated review by prodboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant